package com.coocaa.aries.codegen.service.impl;

import com.coocaa.aries.codegen.biz.ExtConfigTemplateInfoBizImpl;
import com.coocaa.aries.codegen.constant.GlobalConstants;
import com.coocaa.aries.codegen.entity.ExtConfigTemplateInfoEntity;
import com.coocaa.aries.codegen.handler.impl.BaseCodeGenHandlerImpl;
import com.coocaa.aries.codegen.handler.impl.VirgoCodeGenHandlerImpl;
import com.coocaa.aries.codegen.model.CodeGenConfigModel;
import com.coocaa.aries.codegen.model.TableInfoModel;
import com.coocaa.aries.codegen.model.TemplateConfigModel;
import com.coocaa.aries.codegen.model.VirgoTemplateConfigModel;
import com.coocaa.aries.codegen.model.query.DbTableQueryModel;
import com.coocaa.aries.codegen.model.query.ExtCodeGenConfigQueryModel;
import com.coocaa.aries.codegen.service.ICodeGenService;
import com.coocaa.aries.codegen.util.SqlUtil;
import com.coocaa.aries.codegen.validator.CodeGenValidator;
import com.coocaa.aries.codegen.validator.DbValidator;
import com.coocaa.aries.codegen.yml.CodeGenProperties;
import com.coocaa.aries.core.base.model.PageResultModel;
import com.coocaa.aries.core.base.model.R;
import com.coocaa.aries.core.tool.file.FileOpsUtil;
import com.coocaa.aries.core.tool.file.ZipFileUtil;
import com.coocaa.aries.core.tool.random.RandomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * @author : bijiahao
 * @date : 2019/4/20.
 * @description:
 */
@Service
public class CodeGenServiceImpl implements ICodeGenService {
    @Autowired
    private CodeGenProperties codeGenProperties;
    @Autowired
    private ExtConfigTemplateInfoBizImpl extConfigTemplateInfoBiz;

    @Override
    public R execCodeGen(CodeGenConfigModel codeGenConfigModel) throws Exception {
        this.handleCodeGen(codeGenConfigModel);
        //代码生成之后的处理
        handleAfterCodeGen(codeGenConfigModel);
        return R.ok(codeGenConfigModel.getOutputDir());
    }

    private void handleCodeGen(CodeGenConfigModel codeGenConfigModel) throws Exception {
        if (CodeGenValidator.isOriginTableOnly(codeGenConfigModel)){
            if (null == codeGenConfigModel.getTemplateConfig()) {
                codeGenConfigModel.setTemplateConfig(new VirgoTemplateConfigModel());
            }
            VirgoCodeGenHandlerImpl virgoCodeGenHandler = new VirgoCodeGenHandlerImpl();
            //代码生成之前的处理
            handleBeforeCodeGen(codeGenConfigModel);
            virgoCodeGenHandler.execute(codeGenConfigModel);
        }else {
            if (null == codeGenConfigModel.getTemplateConfig()) {
                codeGenConfigModel.setTemplateConfig(new TemplateConfigModel());
            }
            BaseCodeGenHandlerImpl baseCodeGenHandler = new BaseCodeGenHandlerImpl();
            //代码生成之前的处理
            handleBeforeCodeGen(codeGenConfigModel);
            baseCodeGenHandler.execute(codeGenConfigModel);
        }
    }

    /**
     * 获取配置信息
     *
     * @return
     */
    @Override
    public R configInfo() {
        R data = new R("disableLocalRunning", codeGenProperties.isDisableLocalRunning());
        return R.ok(data);
    }

    @Override
    public void downFile(String dir, HttpServletResponse response) throws Exception {
        //非本地运行-服务器生成代码后,下载到本地
        String zipPath = dir + "/" + GlobalConstants.ZIP_FILE_NAME;
        ZipFileUtil.zipFile(dir, zipPath);
        handleDownFile(response, zipPath);
        //完成后,删除文件
        FileOpsUtil.delete(dir);
    }

    @Override
    public PageResultModel<TableInfoModel> listTable(DbTableQueryModel model) {
        SqlUtil sqlUtil = new SqlUtil(model);
        PageResultModel<TableInfoModel> pageResult = sqlUtil.listTableInfo();
        return pageResult;
    }

    @Override
    public PageResultModel<ExtConfigTemplateInfoEntity> listConfigTemplate(ExtCodeGenConfigQueryModel model) {
        return extConfigTemplateInfoBiz.getCommonPageResult(model);
    }

    @Override
    public R testDbConn(DbTableQueryModel model) {
        String result = DbValidator.valid(model);
        if (R.SUCCESS.equals(result)) {
            return R.ok();
        }
        return R.error(result);
    }

    @Override
    public void saveConfigTemplate(ExtConfigTemplateInfoEntity entity) {
        CodeGenValidator.valid(entity);
        if (null == entity.getId()) {
            extConfigTemplateInfoBiz.add(entity);
        }
    }

    /*************** ===私有方法=== ********************* ===start=== ***************************************/
    /**
     * 代码生成之前的处理
     *
     * @param codeGenConfigModel
     */
    private void handleBeforeCodeGen(CodeGenConfigModel codeGenConfigModel) {
        boolean isLocalRunning = CodeGenValidator.isLocalRunning(codeGenConfigModel);
        if (!isLocalRunning) {
            //非本地运行-使用服务器代码存放路径
            String path = convertServerCodeGenStorePath();
            codeGenConfigModel.setOutputDir(path);
        }
    }

    /**
     * 代码生成之后的处理
     *
     * @param codeGenConfigModel
     */
    private void handleAfterCodeGen(CodeGenConfigModel codeGenConfigModel) throws Exception {
        boolean isLocalRunning = CodeGenValidator.isLocalRunning(codeGenConfigModel);
        if (isOpenDirAfterDone(codeGenConfigModel) && isLocalRunning) {
            try {
                String osName = System.getProperty("os.name");
                if (osName != null) {
                    if (osName.contains("Mac")) {
                        Runtime.getRuntime().exec("open " + codeGenConfigModel.getOutputDir());
                    } else if (osName.contains("Windows")) {
                        Runtime.getRuntime().exec("cmd /c start " + codeGenConfigModel.getOutputDir());
                    } else {
                    }
                }
            } catch (IOException var4) {
                var4.printStackTrace();
            }
        }
    }

    /**
     * 下载文件
     *
     * @param response
     * @param path
     * @throws Exception
     */
    private void handleDownFile(HttpServletResponse response, String path) throws Exception {
        response.setContentType("text/html,charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        File file = new File(path);
        FileInputStream in = new FileInputStream(file);
        OutputStream fos = response.getOutputStream();
        response.reset();
        response.setContentType("application/x-download");
        response.setHeader("Content-disposition", "attachment;filename=" + file.getName());
        byte[] b = new byte[2048];
        int read;
        while ((read = in.read(b)) != -1) {
            fos.write(b, 0, read);
        }
        fos.flush();
        in.close();
        fos.close();
    }

    /**
     * 非本地运行-使用服务器代码存放路径
     *
     * @return
     */
    private String convertServerCodeGenStorePath() {
        Assert.hasText(codeGenProperties.getStorePath(), "服务器存放生成代码路径不能为空！");
        StringBuilder path = new StringBuilder();
        path.append(codeGenProperties.getStorePath())
                .append("/")
                .append(RandomUtil.getRandomLongStr());
        return path.toString();
    }

    /**
     * 是否打开生成目录
     *
     * @param codeGenConfigModel
     * @return
     */
    private boolean isOpenDirAfterDone(CodeGenConfigModel codeGenConfigModel) {
        return codeGenConfigModel.getOpenDirAfterDone() != null
                && codeGenConfigModel.getOpenDirAfterDone() == 1;

    }
}
